<template>
	<view class="bigBreakEdit" :style="{ height: webStyle.height }">
		<view class="title-box" :style="{ 'padding-top': inf0Pt + 'vh' }">
			<image class="back" @click="back" :src="imgPath + 'AICont/back-arrow.svg'" mode="widthFix"></image>
			<view class="title">文案详情</view>
			<view class="back"></view>
		</view>
		<view class="main">
			<view class="content">
				<!-- {{ pageInfo.content }} -->
				<scroll-view scroll-y="true" class="scroll-textarea" :scroll-top="scrollHeight">
					<textarea :adjust-position="false" class="textarea" ref="scrollTextarea" placeholder="请输入文案" :auto-height="true" name="aiCont" id="" @input="contentWatch" :maxlength="2000" :value="pageInfo.content"></textarea>
				</scroll-view>
			</view>
			<view class="f">
				<view class="submit" @tap="copy(pageInfo.content)">{{ "复制内容" }}</view>
				<view class="submit" @tap="useCont" :style="{ filter: pageInfo.content ? 'brightness(1)' : 'brightness(0.5)' }">{{ submitBtnText }}</view>
				<view class="submit" @tap="getCont" :style="{ filter: pageInfo.content ? 'brightness(1)' : 'brightness(0.5)' }">{{ "智能改稿" }}</view>
			</view>
		</view>
		<LoginDialog ref="LoginDialog" :show="LoginDialogShow" @successFn="loginDialogShowSucc" @changeShow="changeLoginDialogShow" style="z-index: 999"></LoginDialog>
	</view>
</template>

<script>
import { tools } from "@/utils/util.js";
import myRequest, * as request from "@/utils/api.js";
import * as api from "@/api/createVideo.js";

let contentWatchTimer = null;
let iptTimer = null;
let chatTimer = null;
let dataList = []; // 保存数据流
let renderStart = false; // 开始渲染数据
let getDataEnd = false; // 获取流数据结束
let iterator = null; // 获取数据流迭代器

export default {
	name: "bigBreakEdit",
	data() {
		return {
			imgPath: tools.imgPath,
			inf0Pt: 0,
			systemInfo: {},
			webStyle: {
				height: ""
			},
			LoginDialogShow: false,
			pageInfo: {},
			submitBtnText: "创作视频",
			chatTimer: false,
			requestTask: null,
			scrollHeight: 0
		};
	},
	methods: {
		// 获取系统info
		initSystemInfo(isUpdate = true) {
			const that = this;
			return new Promise((resolve, reject) => {
				uni.getSystemInfo({
					success(payload) {
						if (isUpdate) {
							that.systemInfo = payload;
							that.webStyle.height = `${that.systemInfo.windowHeight}px`;
							console.log("initSystemInfo", that.systemInfo);
							switch (that.systemInfo.uniPlatform) {
								case "web":
									that.inf0Pt = 4.5;
									break;
								case "app":
									that.inf0Pt = 4.5;
									break;
								case "mp-weixin":
									that.inf0Pt = 4.5;
									break;
							}
						}
						resolve(payload);
					}
				});
			});
		},
		// 跳转页面
		toPage(path, type = "navigateTo") {
			uni[type]({
				url: path
			});
		},
		// 回退
		back() {
			let pages = getCurrentPages();
			if (pages.length > 1) {
				uni.navigateBack({
					delta: 1
				});
			} else {
				uni.setStorageSync("toHome", {
					footerBarListAc: 1
				});
				uni.reLaunch({
					url: "/pages/index/index"
				});
			}
		},
		// 获取页面参数
		initPageInfo(opt) {
			let pageInfo = uni.getStorageSync("bigBreakEditInfo");
			this.h1_text = pageInfo.h1_text;
			uni.removeStorageSync("bigBreakEditInfo");
			let pageInfo2 = uni.getStorageSync("AIContInfo");
			uni.removeStorageSync("AIContInfo");
			this.pageInfo = {
				...pageInfo,
				...pageInfo2
			};
		},
		// 监听登录弹出层显示
		changeLoginDialogShow(val) {
			this.LoginDialogShow = val;
		},
		// 登陆成功数据刷新
		loginDialogShowSucc() {
			this.getData();
		},
		// 获取数据
		getData() {},
		// 文案改变
		contentWatch(e) {
			if (contentWatchTimer) {
				clearTimeout(contentWatchTimer);
			}
			contentWatchTimer = setTimeout(async () => {
				contentWatchTimer = null;
				this.pageInfo.content = e.detail.value;
			}, 688);
		},
		// AI改稿
		async getCont() {
			if (this.pageInfo.content == "" || this.chatTimer) return false;
			const that = this;
			// 防止误触
			that.chatTimer = chatTimer = true;

			// 渲染流程开始
			console.log("渲染流程开始~");

			let resList = await new Promise(async (resolve) => {
				dataList = []; // 保存数据流
				renderStart = false; // 开始渲染数据
				getDataEnd = false; // 获取流数据结束
				iterator = dataList[Symbol.iterator](); // 获取数据流迭代器

				// 渲染数据流
				const renderFn = async (iteratorItem, currInd, aaa) => {
					// 缓存当前渲染索引
					let newInd = currInd;
					// 缓存数据列表
					let tempList = JSON.parse(JSON.stringify(dataList));

					if (!iteratorItem.value.isRender) {
						// 表示此数据已渲染(下面是渲染过程)
						iteratorItem.value.isRender = true;

						// 渲染过程=========
						// 获取渲染索引 (用来逐字渲染时从该索引位置渲染)
						currInd = currInd || that.pageInfo.content.length;

						// 逐字展示实现,更新当前渲染索引
						newInd = await that.showTextLoop(that.pageInfo, that.pageInfo.content + iteratorItem.value.text, currInd);
						// 渲染过程结束======
					}

					// 获取后端数据流索引（用来判断当前渲染状态）
					let dataInd = tempList.findIndex((e) => e.id == iteratorItem.value.id);

					if (dataInd == tempList.length - 1) {
						// 这里表示数据列表渲染完成，等待新的后端数据返回，轮询时间为0.15秒
						await new Promise((sleep) => setTimeout(sleep, 150));

						// 递归结束,后端数据已全部获取，数据渲染也全部完成
						// console.log("递归结束,后端数据已全部获取", {newInd, getDataEnd, dataInd, dataList,tempList});
						if (newInd == -1 || (dataList.length == tempList.length && getDataEnd)) {
							console.log("渲染流程结束！");
							chatTimer = null;
							that.chatTimer = false;
							that.submitBtnText = "创作视频";
							return true;
						}

						// 重新等待
						return renderFn(iteratorItem, newInd, "111");
					} else {
						// 这里表示数据列表未完成，执行下一个数据渲染
						return renderFn(iterator.next(), newInd, "222");
					}
				};

				// 开始发送数据
				const token = uni.getStorageSync("token") || uni.getStorageSync("_token");
				const url = "https://ai.yainoo.com/api/aiwork/chat/chat_streamv8";
				let sendData = {
					agentId: "1811635099264049154",
					userInput: "{[" + that.pageInfo.content + "]}" + "\n\n根据以上{[]}内的信息, 生成一次改稿内容，开头和结尾不要出现提示话术，不要副标题，不要出现小红书字样"
				};
				uni.showLoading({
					title: "文案改写中..."
				});
				that.submitBtnText = "文案改写中";

				// #ifndef MP-WEIXIN
				// const postData = {
				// 	// 参数
				// 	tenant_id: 'BIZ',
				// 	card_id: '584415218126295040'
				// }
				// let xhr = new XMLHttpRequest()
				// xhr.open('POST', url, true)
				// xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8')
				// xhr.onprogress = function () {
				//   console.log('流式输出', xhr.responseText)
				// }
				// xhr.onloadend = function () {
				//   console.log('done')
				// }
				// xhr.send(JSON.stringify(postData))
				// return;
				let wsState = "close";
				let wsId = tools.createID();
				let ws = uni.connectSocket({
					url: "ws://175.178.252.101/ws",
					header: {
						Authorization: token,
						"content-type": "application/json"
					},
					// protocols: ["protocol1"],
					multiple: true,
					method: "GET",
					success(res) {
						console.log("ws-succ", res);
					},
					fail(err) {
						uni.hideLoading();
						console.log("ws-fail", err);
					},
					complete() {}
				});
				ws.onOpen((res) => {
					console.log("ws-onOpen", res);
					ws.send({
						data: JSON.stringify({
							msgType: "addUser",
							msgCont: {
								userId: wsId,
								token: token
							}
						})
					});
					wsState = "open";
				});
				ws.onError((err) => {
					console.log("ws-onError", err);
					getDataEnd = true; // 获取流数据结束
					wsState = "close";
				});
				ws.onClose((res) => {
					console.log("ws-onClose", res);
					getDataEnd = true; // 获取流数据结束
					wsState = "close";
				});
				ws.onMessage((res) => {
					// console.log("ws-onMessage", res, res.data);
					if (res.data == "addSuccess") {
						console.log("发起请求！");
						ws.send({
							data: JSON.stringify({
								msgType: "proxy-request",
								msgCont: {
									url: url,
									// url: "http://192.168.124.87:3000/stream",
									// url: "https://ai.yainoo.com/api/aiwork/chat/chat_streamv8",
									method: "POST",
									data: sendData,
									// data: {
									// 	agentId: "1811636375162937346",
									// 	userInput: "你好啊"
									// },
									header: {
										Authorization: token,
										"Content-Type": "application/json",
										Accept: "text/event-stream"
										// Accept: "application/json, text/plain, */*"
									}
								}
							})
						});
					} else {
						let msgData = JSON.parse(res.data);
						switch (msgData.msgType) {
							case "dataItem":
								console.log(msgData.msgCont);
								// 修改数据体
								let resObj = {
									id: tools.createID(),
									data: msgData.msgCont,
									// text: text.slice(text.lastIndexOf("data:")).slice(6),
									text: msgData.msgCont.replace(/\\n/g, "\n"),
									isRender: false
								};
								dataList.push(resObj);
								console.log("resObj:", resObj);
								if (!renderStart) {
									uni.hideLoading();
									renderStart = true; // 开始渲染后端流数据
									that.pageInfo.content = "";
									let iteratorItem = iterator.next();
									renderFn(iteratorItem);
								}
								break;
							case "end":
								console.log(msgData.msgCont);
								getDataEnd = true; // 获取流数据结束
								ws.close();
								break;
							default:
								break;
						}
					}
				});
				// 将ws应用到全局，方便中断请求
				this.requestTask = ws;
				// #endif

				// #ifdef MP-WEIXIN
				let requestTask = uni.request({
					url: url,
					// url: "http://111.0.112.226:18762/chat_stream",
					// url: "http://localhost:3000/stream",
					method: "POST",
					responseType: "text",
					enableChunked: true, // 开启流传输
					header: {
						// "Content-Type": "application/json",
						// Accept: "text/event-stream",
						Authorization: token
					},
					data: sendData,
					success(res) {
						console.log(res);
						getDataEnd = true; // 获取流数据结束
						// #ifndef MP-WEIXIN
						uni.hideLoading();
						let content = res.data
							.replace(/↵/g, "\n")
							.match(/(data:)?(.*)(\n\n)?/g)
							?.map((e) => {
								if (!e) return "";
								let startInd = 0;
								let endInd = e.length;
								if (/data:/.test(e)) {
									startInd = 5;
								}
								if (/\n\n/.test(e)) {
									endInd = -2;
								}
								let resVal = e.slice(startInd, endInd);
								return resVal.replace(/\\n/g, "\n");
							})
							.join("");
						that.pageInfo.content = content;
						that.submitBtnText = "创作视频";
						// #endif
					},
					fail(err) {
						console.log(err);
						chatTimer = null;
						that.chatTimer = false;
						if (err.errMsg != "request:fail abort") {
							tools.easyToast("网络出错!");
							that.pageInfo.content = "网络出错!";
							that.stop();
						} else {
							// tools.easyToast("请求中断!");
						}
						getDataEnd = true; // 获取流数据结束
					}
				});

				// 获取到响应头
				requestTask.onHeadersReceived((res) => {
					console.log(res.header);
					uni.hideLoading();
				});

				// 获取到响应数据
				requestTask.onChunkReceived(async (res) => {
					// arraybuffer转string
					const uint8Array = new Uint8Array(res.data);
					let text = String.fromCharCode.apply(null, uint8Array);
					text = decodeURIComponent(escape(text));

					// 修改数据体
					let resObj = {
						id: tools.createID(),
						data: text,
						// text: text.slice(text.lastIndexOf("data:")).slice(6),
						text: text
							.replace(/↵/g, "\n")
							.match(/(data:)?(.*)(\n\n)?/g)
							?.map((e) => {
								if (!e) return "";
								let startInd = 0;
								let endInd = e.length;
								if (/data:/.test(e)) {
									startInd = 5;
								}
								if (/\n\n/.test(e)) {
									endInd = -2;
								}
								let resVal = e.slice(startInd, endInd);
								return resVal.replace(/\\n/g, "\n");
							})
							.join(""),
						isRender: false
					};
					dataList.push(resObj);
					console.log("resObj:", resObj);
					if (!renderStart) {
						renderStart = true; // 开始渲染后端流数据
						that.pageInfo.content = "";
						let iteratorItem = iterator.next();
						renderFn(iteratorItem);
					}
				});

				// 将requestTask应用到全局，方便中断请求
				this.requestTask = requestTask;
				// #endif
			});
		},
		// 逐字展示效果实现
		showTextLoop(inputEl, text, currInd = 0) {
			let ind = currInd; // 渲染索引
			let renderText = text; // 渲染内容
			return new Promise((next) => {
				let time = tools.randomNum(10, 50); // 设置渲染时间间隔 10~20毫秒
				// #ifdef APP
				time = tools.randomNum(76, 86);
				// #endif
				setTimeout(async () => {
					// 此时可能因为网络问题或者后端服务器奔溃，直接结束流程
					if (!this.chatTimer || !chatTimer) {
						next(-1);
						return -1;
					}

					ind++; // 更新渲染索引
					this.$set(inputEl, "content", renderText.slice(0, ind)); // 渲染数据

					// textarea滚到底部实现===========
					let selector = "scroll-textarea .textarea";
					// 获取该元素
					let el = await new Promise(async (next) => {
						this.$nextTick(async () => {
							let el = await tools.getNode(uni, "." + selector);
							next(el);
						});
					});

					if (!chatTimer[0]) {
						chatTimer = [el.height, el.height]; // 缓存元素高度
					} else {
						chatTimer[1] = el.height; // 更新元素高度
						// 判断元素高度是否变化，如果变化就重新滚到底部
						if (chatTimer[0] != chatTimer[1]) {
							chatTimer[0] = chatTimer[1];
							this.scrollHeight = chatTimer[0];
						} else {
						}
					}
					// 聊天界面滚到底部实现结束=========

					// 递归结束
					if (ind >= renderText.length) {
						next(ind);
						return ind;
					}

					// 开始下一个字渲染
					let newInd = await this.showTextLoop(inputEl, text, ind);

					// console.log("逐字展示效果实现22", { newInd });
					next(newInd);
					return newInd;
				}, time);
			});
		},
		// 停止渲染
		stop() {
			chatTimer = null;
			this.chatTimer = false;
			getDataEnd = true;
			// #ifdef MP-WEIXIN
			this.requestTask?.abort();
			// #endif
			// #ifndef MP-WEIXIN
			this.requestTask?.close();
			// #endif
		},
		// 复制
		copy(text = "") {
			uni.setClipboardData({
				data: text,
				success() {
					tools.easyToast("复制成功！");
				},
				fail(err) {
					console.log(err);
				}
			});
		},
		// 使用文本
		useCont(item, index) {
			if (this.pageInfo.content == "" || this.submitBtnText != "创作视频") return;
			uni.setStorageSync("aiCont", {
				updateType: "AiCont",
				cont: this.pageInfo.content
			});
			let pages = getCurrentPages();
			let pageInd = -1;
			switch (this.pageInfo?.toPage) {
				case "index/2": //AI文案
					let [pageName, footerBarListAc] = this.pageInfo.toPage.split("/");
					uni.setStorageSync("toHome", {
						footerBarListAc: footerBarListAc
					});
					pageInd = pages.findIndex((e) => e.route == "pages/index/index");
					if (pageInd != -1) {
						uni.navigateBack({
							delta: pages.length - (pageInd + 1)
						});
					} else {
						uni.reLaunch({
							url: `/pages/${pageName}/${pageName}`
						});
					}
					break;
				default:
					pageInd = pages.findIndex((e) => e.route == "pages/createVideo/createVideo");
					console.log(pageInd, "/pages/createVideo/createVideo", pages);
					if (pageInd != -1) {
						uni.navigateBack({
							delta: pages.length - (pageInd + 1)
						});
					} else {
						this.toPage("/pages/createVideo/createVideo", "reLaunch");
					}
					break;
			}
		}
	},
	onLoad(opt) {
		this.initSystemInfo();
		this.initPageInfo(opt);
		this.getData();
	},
	beforeDestroy() {
		this.stop();
	}
};
</script>

<style lang="scss">
::-webkit-scrollbar {
	width: 0vw !important;
	height: 0vw !important;
	display: none;
}

.bigBreakEdit {
	width: 100vw;
	// height: 100vh;
	background: #0c1411;
	position: relative;
	color: #fff;
	overflow: hidden;
	display: flex;
	flex-direction: column;

	.title-box {
		display: flex;
		justify-content: space-between;
		align-items: center;
		box-sizing: border-box;
		padding: 2vw;
		.back {
			width: 6vw;
		}

		.title {
			font-size: 36rpx;
			font-weight: 400;
			color: rgba(255, 255, 255, 1);
		}
	}
	.main {
		flex: 1;
		display: flex;
		flex-direction: column;
		overflow: hidden;
		.content {
			width: 86%;
			margin: 6vw auto;
			box-sizing: border-box;
			padding: 3vw;
			flex: 1;
			overflow: hidden;
			border-radius: 2.5vw;
			background: rgba(255, 255, 255, 0.068);
			word-wrap: break-word;
			overflow-wrap: break-word;
			line-height: 20px;
			display: flex;
			flex-direction: column;
			.scroll-textarea {
				width: 100%;
				flex: 1;
				overflow: hidden;
				.textarea {
					display: block;
					width: 100%;
					height: 100%;
					font-size: 4.6vw;
					line-height: 20px;
				}
			}
		}
		.f {
			width: 86%;
			margin: 6vw auto;
			box-sizing: border-box;
			// padding: 10vw 0vw;
			position: relative;
			display: flex;
			justify-content: space-between;
			align-items: center;
			.submit {
				width: 30%;
				opacity: 1;
				border-radius: 10px;
				background: rgba(0, 153, 127, 1);
				display: flex;
				justify-content: center;
				align-items: center;
				font-size: 3.6vw;
				font-weight: 500;
				color: rgba(255, 255, 255, 1);
				padding: 2.5vw 0vw;
				margin-bottom: 3vw;
			}
		}
	}
}
</style>
